// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

#nullable enable

using System.Threading;
using System.Threading.Tasks;
using NuGet.Common;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using NuGet.Protocol.Model;

namespace NuGet.Commands
{
    internal sealed class VulnerabilityInformationProvider : IVulnerabilityInformationProvider
    {
        private readonly SourceRepository _source;
        private readonly ILogger _logger;

        private readonly AsyncLazy<GetVulnerabilityInfoResult?> _vulnerabilityInfo;

        public VulnerabilityInformationProvider(SourceRepository source, ILogger logger)
        {
            _source = source;
            _logger = logger;

            _vulnerabilityInfo = new AsyncLazy<GetVulnerabilityInfoResult?>(GetVulnerabilityInfoAsync);
        }

        public async Task<GetVulnerabilityInfoResult?> GetVulnerabilityInformationAsync(CancellationToken cancellationToken)
        {
            GetVulnerabilityInfoResult? result = await _vulnerabilityInfo;
            return result;
        }

        private async Task<GetVulnerabilityInfoResult?> GetVulnerabilityInfoAsync()
        {
            IVulnerabilityInfoResource vulnerabilityInfoResource =
                await _source.GetResourceAsync<IVulnerabilityInfoResource>(CancellationToken.None);
            if (vulnerabilityInfoResource is null)
            {
                return null;
            }

            // Don't re-use a SourceCacheContext from whatever triggered this, because installing packages
            // (and a few other scenarios, look at everything that calls SourceCacheContext.MaxAge's setter)
            // will ignore the http cache, because it wants to allow newly published packages to be installable.
            // However, in VS, when a new project template installs packages, we don't want to force a re-download
            // of the vulnerability data. Firstly, from a customer point of view, it's not necessary. The reason
            // we bust the cache for package install doesn't apply to vulnerability data. Secondly, it triggers
            // regressions in VS's performance tests.
            using SourceCacheContext cacheContext = new();
            GetVulnerabilityInfoResult result = await vulnerabilityInfoResource.GetVulnerabilityInfoAsync(cacheContext, _logger, CancellationToken.None);
            return result;
        }
    }
}
